package com.yonyou.crm.cum.cumprmt.service;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;





import com.yonyou.crm.bpub.approval.entity.ApprovalStatusEnum;
import com.yonyou.crm.bpub.approval.entity.DjTypeEnum;
import com.yonyou.crm.bpub.approval.entity.ProcessInstanceVO;
import com.yonyou.crm.bpub.approval.entity.ProcessModelVO;
import com.yonyou.crm.bpub.approval.entity.SuperVO;
import com.yonyou.crm.bpub.approval.service.ProcessBizServiceImpl;
import com.yonyou.crm.bpub.approval.service.ProcessInstanceBizServiceImpl;
import com.yonyou.crm.bpub.approval.service.ProcessModelBizServiceImpl;
import com.yonyou.crm.bpub.itf.IProcessService;
import com.yonyou.crm.bpub.list.entity.AppListVO;
import com.yonyou.crm.bpub.list.entity.AppListValueVO;
import com.yonyou.crm.common.biz.service.BaseBizServiceImpl;
import com.yonyou.crm.common.enumeration.service.EnumBizServiceImpl;
import com.yonyou.crm.common.exception.CrmBusinessException;
import com.yonyou.crm.common.exception.CrmMessageException;
import com.yonyou.crm.common.field.handler.FieldRelationHandler;
import com.yonyou.crm.common.field.relation.EnumFieldRelation;
import com.yonyou.crm.common.field.relation.FieldRelation;
import com.yonyou.crm.common.field.relation.RefFieldRelation;
import com.yonyou.crm.common.login.context.LoginContextConstant;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.crm.common.rest.constant.AppCodeConstant;
import com.yonyou.crm.common.rest.constant.CrmCodeConstant;
import com.yonyou.crm.cum.cumprmt.entity.CumprmtVO;
import com.yonyou.crm.cum.customer.dynamic.DymCumUpgradeApply;
import com.yonyou.crm.cum.customer.dynamic.DymCumUpgradeSuccess;
import com.yonyou.crm.cum.customer.entity.CumGroupTypeEnum;
import com.yonyou.crm.cum.customer.entity.CustomerVO;
import com.yonyou.crm.cum.customer.service.CustomerBizServiceImpl;
import com.yonyou.crm.sys.dynamic.impl.DynamicServiceImpl;
import com.yonyou.crm.sys.org.service.SysOrgBizServiceImpl;
import com.yonyou.crm.sys.user.entity.UserVO;
import com.yonyou.crm.sys.user.service.UserBizServiceImpl;
import com.yonyou.iuap.context.InvocationInfoProxy;

@Service
public class CumprmtBizServiceImpl extends BaseBizServiceImpl<CumprmtVO> implements IProcessService{

	@Autowired
	private UserBizServiceImpl userService;
	@Autowired
	private SysOrgBizServiceImpl orgService;
	@Autowired
	private EnumBizServiceImpl enumService;
	
	@Autowired
	private CustomerBizServiceImpl cumService;
	
	@Autowired
	private ProcessBizServiceImpl processService;
	
	@Autowired
	private ProcessInstanceBizServiceImpl instanceService;
	
	@Autowired
	private ProcessModelBizServiceImpl processModelService;
	@Autowired
	private DynamicServiceImpl dynamicService;
	/*
	 * 根据id获取详情
	 */
	public <T extends Serializable> T selectById(Long id) {
		CumprmtVO vo = getVOById(CumprmtVO.class, id);
		transCumprmt(Arrays.asList(vo));
		SuperVO voo = vo;
		return (T)voo;
	}
	
	public Page<CumprmtVO> getCumprmtList(Page<CumprmtVO> page,Map<String, Object> paraMap) {
			
		Page<CumprmtVO> cumprmtPage = null;
		if (paraMap != null) {
			cumprmtPage = super.pageSelect(CumprmtVO.class, page, paraMap.keySet().toArray(new String[0]), paraMap.values().toArray(new Object[0]));
		}
		else {
			cumprmtPage = super.pageSelect(CumprmtVO.class, page, null, null);
		}
		
		transCumprmt(cumprmtPage.getData());
		
		return cumprmtPage;
	}
	
	private List<CumprmtVO> transCumprmt(List<CumprmtVO> list) {
		
		if (list != null && list.size() > 0) {
			
			List<FieldRelation<CumprmtVO>> relations = new ArrayList<FieldRelation<CumprmtVO>>();
			relations.add(new RefFieldRelation<CumprmtVO>(CumprmtVO.class, "applyUserId", new String[]{"applyUserName"}, userService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<CumprmtVO>(CumprmtVO.class, "commitUserId", new String[]{"commitUserName"}, userService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<CumprmtVO>(CumprmtVO.class, "approvalUserId", new String[]{"approvalUserName"}, userService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<CumprmtVO>(CumprmtVO.class, "orgId", new String[]{"orgName"}, orgService, "selectFieldsByIds"));
			relations.add(new RefFieldRelation<CumprmtVO>(CumprmtVO.class, "deptId", new String[]{"deptName"}, orgService, "selectFieldsByIds"));
			relations.add(new EnumFieldRelation<CumprmtVO>(CumprmtVO.class, "approvalState", "approvalStateName", enumService, "approval_state"));
			
			new FieldRelationHandler<CumprmtVO>().handler(list, relations);
			for(CumprmtVO vo : list){
				if(vo.getApprovalState() == 0 && vo.getApplyUserId() != null){
					vo.setApprovalStateName("已驳回");
				}else if(vo.getApprovalState() == 0 && vo.getApplyUserId() == null){
					vo.setApprovalStateName("已撤回");
				}
			}
		}
		
		return list;
	}
	
	/*
	 * 获取升级申请单(要确保一个客户只有一个未删除的升级申请单)
	 */
	public List<CumprmtVO> selectByCumId(Long cumId) {
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("tenantId", Long.parseLong(InvocationInfoProxy.getTenantid()));
		paraMap.put("cumId", cumId);
		
		List<CumprmtVO> list = dao.selectVoList(CumprmtVO.class, "selectByCumId", paraMap);
		transCumprmt(list);
		
		return list;
	}
	
	/**
	 * 获取客户相关对象客户升级申请单
	 * @param paraMap
	 * @return
	 */
	public List<CumprmtVO> selectCumprmtByCumId(Map<String, Object> paraMap) {
		List<CumprmtVO> list = dao.selectVoList(CumprmtVO.class, "selectByCumId", paraMap);
		transCumprmt(list);
		return list;
	}
	/**
	 * 根据客户id查询客户升级申请单
	 * @param cumId
	 * @return
	 */
	public Map<String,Object> getRelListForApp(Long cumId, Integer limit){
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("tenantId", Long.parseLong(InvocationInfoProxy.getTenantid()));
		paraMap.put("cumId", cumId);
        List<CumprmtVO> listForNum = this.selectCumprmtByCumId(paraMap);
		paraMap.put("limit", limit);
		List<CumprmtVO> list = this.selectCumprmtByCumId(paraMap);
		int num = list == null ? 0:list.size();
		Map<String,Object> datalistMap = new HashMap<String,Object>();

		if(list != null && list.size() >0 ){

			List<AppListVO> listapp = new ArrayList<AppListVO>();
			for(CumprmtVO vo : list){
				AppListVO listVO = new AppListVO();
				listVO.setId(vo.getId());
				
				List<List<AppListValueVO>> valueList = new ArrayList<List<AppListValueVO>>();
				List<AppListValueVO> colList = new ArrayList<AppListValueVO>();
				Map<String, String> hidelist = new HashMap<String, String>();
				int djType = DjTypeEnum.CUM_PRMT.getValue();
				hidelist.put("type", String.valueOf(djType));
				ProcessInstanceVO instanceVO = instanceService.selectByPk(vo.getId(), djType);
				if (instanceVO != null) {
					hidelist.put("instanceid", instanceVO.getYsInstanceId());
				}
				
				AppListValueVO listValue = new AppListValueVO();
				listValue.setItemkey("orgName");
				listValue.setDisplayvalue(vo.getOrgName());
				colList.add(listValue);
				
				listValue = new AppListValueVO();
				listValue.setItemkey("approvalTime");
				String approvalTime = "";
				try {
					approvalTime = formateDate(vo.getApprovalTime(), "yyyy-MM-dd HH:mm");
				} catch (CrmMessageException e) {
					e.printStackTrace();
				}
				listValue.setDisplayvalue(approvalTime);
				colList.add(listValue);
				
				listValue = new AppListValueVO();
				listValue.setItemkey("approvalUserName");
				listValue.setDisplayvalue(vo.getApprovalUserName());
				colList.add(listValue);
				
				listValue = new AppListValueVO();
				listValue.setItemkey("approvalStateName");
				listValue.setDisplayvalue(vo.getApprovalStateName());
				colList.add(listValue);
				
				valueList.add(colList);
				listVO.setValuelist(valueList);
				listVO.setHidelist(hidelist);
				listapp.add(listVO);

			}
			datalistMap.put("type", "cumprmt");
			datalistMap.put("name", "客户升级申请单");
			datalistMap.put("num", listForNum == null ? 0 : listForNum.size());
			datalistMap.put("isnew", "N");
			datalistMap.put("detaillist", listapp);
		}
		return datalistMap;
		
	}
	/*
	 * 获取升级申请单(一个客户有多个升级申请单，只有一个是当前进行中的，字段approval_state<>0为进行中的升级单)
	 */
	public CumprmtVO selectCurrentByCumId(Long cumId) {
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("tenantId", Long.parseLong(InvocationInfoProxy.getTenantid()));
		paraMap.put("cumId", cumId);
		
		Object object = dao.selectOne(CumprmtVO.class, "selectCurrentByCumId", paraMap);
		if (object == null) {
			return null;
		}
		return (CumprmtVO)object;
	}
	
	/*
	 * 检查客户身份的唯一项，包括纳税人识别号或证件类型+证件号，如都为空则返回true
	 */
	private boolean isEmptyOfCustomerVerify(CustomerVO cumVo) {
		boolean isVerifyEmpty = false;
		boolean isTaxpayerNoEmpty = false;
		boolean isDocEmpty = false;
		
		if (cumVo.getTaxpayerNo() == null || cumVo.getTaxpayerNo().isEmpty()) {
			isTaxpayerNoEmpty = true;
		}
		if ((cumVo.getDocType() == null || cumVo.getDocType().equals(0)) && (cumVo.getDocNum() == null || cumVo.getDocNum().isEmpty())) {
			isDocEmpty = true;
		}
		if (isTaxpayerNoEmpty && isDocEmpty) {
			isVerifyEmpty = true;
		}
		return isVerifyEmpty;
	}
	
	/*
	 * 提交升级申请
	 */
	public void submit(Long cumId) {
		
		// 取customer
		CustomerVO cumVo = cumService.getDetail(cumId);
		//判断客户是否停用
		if(cumVo.getEnableState() == 2){
			throw new CrmBusinessException("该客户已停用");
		}
        
		if (cumVo == null || cumVo.getId() == null) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "请选择客户");
		}
		
		if (isEmptyOfCustomerVerify(cumVo)) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "客户升级时必须维护客户的[纳税人识别号] 或[证件类型+证件号]");
		}
		
		if (cumVo.getIsGroup() == CumGroupTypeEnum.GROUP.getValue()) {
			throw new CrmBusinessException(CrmCodeConstant.ServerError, "客户已经升级");
		}
		//插入动态(提交客户申请)
		CustomerVO vo = cumService.getDetail(cumId);
        UserVO user = cumService.getCurrentUser();
        Long[] relUserArr = cumService.handleRelUserList(cumId);
		DymCumUpgradeApply cumUpgradeApply = new DymCumUpgradeApply(dynamicService,user,vo,relUserArr);
		cumUpgradeApply.execute();
		
		Long bizTypeId = 0L;
		ProcessModelVO processModelVO = processModelService.selectByType(bizTypeId, DjTypeEnum.CUM_PRMT.getValue());
		if (processModelVO == null) {
			// 没有审批流，直接生效,不生成升级单.
			cumVo.setIsGroup(CumGroupTypeEnum.GROUP.getValue());
			cumService.updateNoAuthority(cumVo);
			//插入动态(提交申请成功)
			DymCumUpgradeSuccess cumUpgradeSucc = new DymCumUpgradeSuccess(dynamicService,user,vo,relUserArr);
			cumUpgradeSucc.execute();
			return;
		}
		
		CumprmtVO prmtVo = selectCurrentByCumId(cumId);
		if (prmtVo == null) {
			// 新增单据
			prmtVo = new CumprmtVO();
			prmtVo.setOrgId(Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.OrgId)));
			prmtVo.setTenantId(Long.parseLong(InvocationInfoProxy.getTenantid()));
			prmtVo.setDeptId(Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.DeptId)));
			Long userId = Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId));
			prmtVo.setApplyUserId(userId);
			prmtVo.setCumId(cumId);
			prmtVo.setCumName(cumVo.getName());
			prmtVo.setCumFullname(cumVo.getFullname());
			prmtVo.setCommitUserId(userId);
			prmtVo.setCommitTime(new Date());
			prmtVo.setApprovalState(ApprovalStatusEnum.NOT_COMMIT.getValue());
			
			prmtVo = saveVO(prmtVo);
		} else {
			if (prmtVo.getApprovalState().equals(ApprovalStatusEnum.NOT_COMMIT.getValue())) {
				// 更改审批状态为已提交
				updateApprovalState(prmtVo.getId(), ApprovalStatusEnum.NOT_COMMIT.getValue(), null);
			} if (prmtVo.getApprovalState().equals(ApprovalStatusEnum.FINISHED.getValue())) {
				Map<String, Object> paraMap = new HashMap<String, Object>();
				paraMap.put("comment", "");
				paraMap.put("action", "");
				updateApprovalState(prmtVo.getId(), ApprovalStatusEnum.NOT_COMMIT.getValue(), paraMap);
			} else {
				throw new CrmBusinessException(CrmCodeConstant.ServerError, "升级申请已提交");
			}
			
		}
		
		// 流程启动
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("djType", DjTypeEnum.CUM_PRMT.getValue());
		paraMap.put("bizTypeId", 0L);
		paraMap.put("businessId", prmtVo.getId());
		String instanceName = DjTypeEnum.CUM_PRMT.getName() + "-" + prmtVo.getCumName();
		paraMap.put("instanceName", instanceName);
		processService.startProcess(paraMap);
		
		updateApprovalState(prmtVo.getId(), ApprovalStatusEnum.COMMITED.getValue(), null);
	}
	
	/*
	 * 更新单据审批状态
	 */
	public void updateApprovalState(Long id, int approvalState, Map<String, Object> paraMap) {
		CumprmtVO vo = new CumprmtVO();
		vo.setId(id);
		vo.setApprovalState(approvalState);
		
		// 当paraMap不为null时，更新升级表中的审批人，审批时间，审批动作，审批意见
		if (paraMap != null) {
			Long userId = Long.parseLong(InvocationInfoProxy.getParameter(LoginContextConstant.UserId));
			vo.setApprovalUserId(userId);
			vo.setApprovalTime(new Date());
			if (paraMap.containsKey("comment")) {
				vo.setApprovalComment((String)paraMap.get("comment"));
			}
			if (paraMap.containsKey("action")) {
				vo.setApprovalAction((String)paraMap.get("action"));
			}
		}
		
		dao.update(vo);

		// 如果审批状态为已完成，更新客户的is_group为集团客户
		if (approvalState == ApprovalStatusEnum.FINISHED.getValue()) {
			vo = getVOById(CumprmtVO.class, id);
			CustomerVO customerVO = new CustomerVO();
			customerVO.setId(vo.getCumId());
			customerVO.setIsGroup(CumGroupTypeEnum.GROUP.getValue());
			//插入动态(提交申请成功)
			UserVO user = cumService.getCurrentUser();
			Long[] relUserArr = cumService.handleRelUserList(vo.getCumId());
			CustomerVO customer = cumService.getDetail(vo.getCumId());
			DymCumUpgradeSuccess cumUpgradeSucc = new DymCumUpgradeSuccess(dynamicService,user,customer,relUserArr);
			cumUpgradeSucc.execute();
			
			try {
				cumService.updateNoAuthority(customerVO);
			} catch (Exception e) {
				// 什么都不做，如果客户的is_group没有更新成功，可以继续提交升级单
			}
		}
	}
	
	/**
	 * 格式化日期类型数据
	 * @param date
	 * @param dateFormate
	 * @return
	 * @throws CrmMessageException
	 */
	public String formateDate(Date date, String dateFormate) throws CrmMessageException{
		if (date == null) {
			return "";
		}
		String[] dateFormateArr = {"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd HH:mm"};
		if (!Arrays.asList(dateFormateArr).contains(dateFormate)) {
			throw new CrmMessageException(AppCodeConstant.ServerError, "日期格式化格式错误");
		}
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormate);
		return sdf.format(date);
	}
	
}
